<template>
  <v-dialog v-model="dialogFormVisible" max-width="1200px" persistent>
    <v-card>
      <v-card-title>{{ title }}</v-card-title>

      <v-card-text>
        <!-- 基本信息表单 -->
        <v-form ref="formRef" v-model="formValid">
          <v-row>
            <v-col cols="12" md="4">
              <v-text-field v-model="form.tempName" label="模板名称" :rules="rules.tempName" variant="outlined"
                density="compact" required />
            </v-col>
            <v-col cols="12" md="4">
              <v-select v-model="form.tableType" :items="dict.table_type" item-title="dictName" item-value="dictValue"
                label="表类型" :rules="rules.tableType" variant="outlined" density="compact" clearable required />
            </v-col>
            <v-col cols="12" md="4">
              <v-text-field v-model="form.remark" label="备注信息" variant="outlined" density="compact" />
            </v-col>
          </v-row>
        </v-form>

        <!-- 代码编辑器区域 -->
        <div class="code-editor-section mt-4">
          <v-tabs v-model="activeName" bg-color="primary" class="rounded-lg" dark>
            <v-tab value="0">后端模板</v-tab>
            <v-tab value="1">前端模板</v-tab>
          </v-tabs>

          <!-- 后端模板 -->
          <v-card v-show="activeName === '0'" variant="outlined" class="mt-2">
            <v-tabs v-model="backendTabs.active" show-arrows slider-color="primary" class="file-tabs">
              <v-tab v-for="item in backendTabs.data" :key="item.fileName" :value="item.fileName" class="file-tab">
                <span class="tab-text">{{ item.fileName }}</span>
                <v-btn icon="mdi-close" size="x-small" variant="text" class="close-btn"
                  @click.stop="removeTab('backend', item.fileName)" />
              </v-tab>
              <v-tab @click.stop="addTab('backend')" class="add-tab">
                <v-icon size="small">mdi-plus</v-icon>
                <span class="ml-1">新增文件</span>
              </v-tab>
            </v-tabs>

            <!-- 文件内容区域 -->
            <div v-for="item in backendTabs.data" :key="item.fileName" v-show="backendTabs.active === item.fileName"
              class="file-content">
              <v-card-text>
                <!-- 文件配置 -->
                <v-row>
                  <v-col cols="9">
                    <v-text-field v-model="item.path" label="路径前缀" variant="outlined" density="compact" hide-details />
                  </v-col>
                  <v-col cols="3">
                    <v-select v-model="item.ignoreFileName" :items="dict.no_yes" item-title="dictName"
                      item-value="dictValue" label="忽略文件名" variant="outlined" density="compact" clearable
                      hide-details />
                  </v-col>
                </v-row>

                <!-- 代码编辑器 -->
                <v-textarea v-model="item.fileContent" label="代码内容" variant="outlined" rows="15" no-resize
                  class="code-textarea mt-6"
                  @update:model-value="(value: string) => updateFileContent(item.fileName, value)" />
              </v-card-text>
            </div>
          </v-card>

          <!-- 前端模板 -->
          <v-card v-show="activeName === '1'" variant="outlined" class="mt-2">
            <v-tabs v-model="frontendTabs.active" show-arrows slider-color="primary" class="file-tabs">
              <v-tab v-for="item in frontendTabs.data" :key="item.fileName" :value="item.fileName" class="file-tab">
                <span class="tab-text">{{ item.fileName }}</span>
                <v-btn icon="mdi-close" size="x-small" variant="text" class="close-btn"
                  @click.stop="removeTab('frontend', item.fileName)" />
              </v-tab>
              <v-tab @click.stop="addTab('frontend')" class="add-tab">
                <v-icon size="small">mdi-plus</v-icon>
                <span class="ml-1">新增文件</span>
              </v-tab>
            </v-tabs>

            <!-- 文件内容区域 -->
            <div v-for="item in frontendTabs.data" :key="item.fileName" v-show="frontendTabs.active === item.fileName"
              class="file-content">
              <v-card-text>
                <!-- 文件配置 -->
                <v-row>
                  <v-col cols="9">
                    <v-text-field v-model="item.path" label="路径前缀" variant="outlined" density="compact" hide-details />
                  </v-col>
                  <v-col cols="3">
                    <v-select v-model="item.ignoreFileName" :items="dict.no_yes" item-title="dictName"
                      item-value="dictValue" label="忽略文件名" variant="outlined" density="compact" clearable
                      hide-details />
                  </v-col>
                </v-row>

                <!-- 代码编辑器 -->
                <div class="code-editor-container mt-3">
                  <v-textarea v-model="item.fileContent" label="代码内容" variant="outlined" rows="15" no-resize
                    class="code-textarea bg-grey-lighten-3" style="background-color: #f5f5f5;"
                    @update:model-value="(value: string) => updateFileContent(item.fileName, value)" />
                </div>
              </v-card-text>
            </div>
          </v-card>
        </div>
      </v-card-text>

      <v-card-actions>
        <v-btn color="info" variant="outlined" @click="openEnjoyDoc">
          <v-icon start>mdi-book-open-page-variant</v-icon>
          查看模板语法
        </v-btn>
        <v-spacer />
        <v-btn color="grey-darken-1" variant="text" @click="close">
          取消
        </v-btn>
        <v-btn color="primary" variant="text" @click="save">
          确定
        </v-btn>
      </v-card-actions>
    </v-card>

    <!-- 添加文件名对话框 -->
    <v-dialog v-model="addFileDialog" max-width="400px">
      <v-card>
        <v-card-title>添加新文件</v-card-title>
        <v-card-text>
          <v-text-field v-model="newFileName" label="请输入文件名" :rules="fileNameRules" variant="outlined" density="compact"
            autofocus @keyup.enter="confirmAddFile" />
        </v-card-text>
        <v-card-actions>
          <v-spacer />
          <v-btn color="grey-darken-1" variant="text" @click="addFileDialog = false">
            取消
          </v-btn>
          <v-btn color="primary" variant="text" @click="confirmAddFile">
            确定
          </v-btn>
        </v-card-actions>
      </v-card>
    </v-dialog>
  </v-dialog>
</template>

<script setup lang="ts">
import { ref, reactive, nextTick, onMounted, watch } from 'vue';
import { doInsert, doUpdate, getDetailListByParentId } from '@/api/generator/template/GenTemplateManagement';
import { deepClone } from '@/utils/clone';
import { isNull } from '@/utils/validate';
import { formateDate } from '@/utils/format';
import { validatorRule } from '@/utils/validateRule';
import { getDictListSync } from '@/utils/dict';
import { useMessage } from '@/composables/useMessage';
import groupBy from 'lodash/groupBy';

const { success: showSuccess, error: showError } = useMessage();

// 基础数据
const dialogFormVisible = ref(false);
const title = ref('');
const formValid = ref(false);
const formRef = ref();
const addFileDialog = ref(false);
const newFileName = ref('');
const currentTabType = ref<'backend' | 'frontend'>('backend');

const form = reactive<any>({
  tempName: '',
  tableType: '',
  remark: '',
  version: 0,
});

const dict = reactive({
  no_yes: [] as any[],
  table_type: [] as any[],
});

// 验证规则
const rules = {
  tempName: [
    (v: string) => !!v || '模板名称不能为空',
    (v: string) => validatorRule.IS_GENERAL_WITH_CHINESE(v) || '只能包含汉字、字母、数字和下划线',
  ],
  tableType: [
    (v: string) => !!v || '表类型不能为空',
  ],
};

const fileNameRules = [
  (v: string) => !!v || '文件名不能为空',
  (v: string) => {
    const currentTabs = currentTabType.value === 'backend' ? backendTabs : frontendTabs;
    const exists = currentTabs.data.some(item => item.fileName === v);
    return !exists || '文件名已存在';
  },
];

// Tab 管理
const activeName = ref('0');
const backendTabs = reactive({
  data: [] as any[],
  active: '',
});
const frontendTabs = reactive({
  data: [] as any[],
  active: '',
});

const newTabTemplate = {
  type: '',
  path: '',
  fileName: '',
  fileContent: '',
  ignoreFileName: '0',
};

// 显示编辑对话框
function showEdit(row?: any) {
  if (!row) {
    title.value = 'Enjoy模板引擎 - 添加';
    Object.assign(form, {
      tempName: '',
      tableType: '',
      remark: '',
      version: 0,
    });
  } else {
    title.value = 'Enjoy模板引擎 - 编辑';
    Object.assign(form, row);
  }
  dialogFormVisible.value = true;
  fetchData();
}

// 关闭对话框
function close() {
  dialogFormVisible.value = false;
  nextTick(() => {
    if (formRef.value) {
      formRef.value.reset();
    }
    // 重置数据
    Object.assign(form, {
      tempName: '',
      tableType: '',
      remark: '',
      version: 0,
    });
    activeName.value = '0';
    backendTabs.data = [];
    backendTabs.active = '';
    frontendTabs.data = [];
    frontendTabs.active = '';
  });
}

// 保存
async function save() {
  if (!formRef.value) return;

  try {
    const isValid = await formRef.value.validate();
    if (!isValid) return;

    const tmp: any = deepClone(form);
    tmp.detailList = [];

    // 合并后端和前端数据
    backendTabs.data.forEach((item: any) => {
      tmp.detailList.push({ ...item, type: '0' });
    });
    frontendTabs.data.forEach((item: any) => {
      tmp.detailList.push({ ...item, type: '1' });
    });

    // 处理表单数据
    handlerFormData(tmp);

    // 提交保存
    if (!isNull(tmp.id)) {
      const { data } = await doUpdate(tmp);
      showSuccess(data?.msg || '更新成功');
    } else {
      const { data } = await doInsert(tmp);
      showSuccess(data?.msg || '添加成功');
    }

    // 通知父组件刷新数据
    emit('fetchData');
    close();
  } catch (error) {
    console.error('保存失败:', error);
    showError('保存失败');
  }
}

// 处理表单数据
function handlerFormData(formData: any) {
  if (!isNull(formData)) {
    for (const key in formData) {
      if (Object.prototype.toString.call(formData[key]) === '[object Date]') {
        formData[key] = formateDate(formData[key], 'yyyy-MM-dd hh:mm:ss');
      }
    }
  }
}

// 更新文件内容
function updateFileContent(fileName: string, content: string) {
  const currentTabs = activeName.value === '0' ? backendTabs : frontendTabs;
  const tab = currentTabs.data.find(item => item.fileName === fileName);
  if (tab) {
    tab.fileContent = content;
  }
}

// 添加 Tab
function addTab(type: 'backend' | 'frontend') {
  currentTabType.value = type;
  newFileName.value = '';
  addFileDialog.value = true;
}

// 确认添加文件
function confirmAddFile() {
  if (!newFileName.value.trim()) {
    showError('请输入文件名');
    return;
  }

  const currentTabs = currentTabType.value === 'backend' ? backendTabs : frontendTabs;
  const exists = currentTabs.data.some(item => item.fileName === newFileName.value);
  if (exists) {
    showError('文件名已存在');
    return;
  }

  const tabData = deepClone(newTabTemplate);
  tabData.type = currentTabType.value === 'backend' ? '0' : '1';
  tabData.fileName = newFileName.value;
  tabData.fileContent = `// ${newFileName.value}\n// 请在此处编写代码模板\n`;

  currentTabs.data.push(tabData);
  currentTabs.active = newFileName.value;
  addFileDialog.value = false;
}

// 删除 Tab
function removeTab(type: 'backend' | 'frontend', fileName: string) {
  const currentTabs = type === 'backend' ? backendTabs : frontendTabs;

  // 确认删除
  if (!confirm(`确定要删除文件 "${fileName}" 吗？`)) {
    return;
  }

  const index = currentTabs.data.findIndex(tab => tab.fileName === fileName);
  if (index !== -1) {
    currentTabs.data.splice(index, 1);

    // 如果删除的是当前激活的 tab，需要切换到其他 tab
    if (currentTabs.active === fileName) {
      if (currentTabs.data.length > 0) {
        // 选择相邻的 tab
        const newIndex = index < currentTabs.data.length ? index : index - 1;
        currentTabs.active = currentTabs.data[newIndex]?.fileName || '';
      } else {
        currentTabs.active = '';
      }
    }
  }
}

// 打开文档
function openEnjoyDoc() {
  window.open('https://jfinal.com/doc/6-1', '_blank');
}

// 获取数据
async function fetchData() {
  try {
    // 如果是新增，不需要加载详情
    if (!form.id) return;

    const { data } = await getDetailListByParentId(form.id);
    if (data && data.length > 0) {
      const groupedData = groupBy(data, 'type');

      // 后端数据
      const backendData = groupedData['0'];
      if (backendData && backendData.length > 0) {
        backendTabs.data = backendData;
        backendTabs.active = backendData[0].fileName;
      }

      // 前端数据
      const frontendData = groupedData['1'];
      if (frontendData && frontendData.length > 0) {
        frontendTabs.data = frontendData;
        frontendTabs.active = frontendData[0].fileName;
      }
    }
  } catch (error) {
    console.error('获取详情数据失败:', error);
  }
}

// 初始化字典数据
function initDict() {
  try {
    dict.no_yes = getDictListSync('no_yes') || [];
    dict.table_type = getDictListSync('table_type') || [];
  } catch (error) {
    console.error('获取字典数据失败:', error);
  }
}

// 暴露方法
defineExpose({
  showEdit,
});

// 事件发射
const emit = defineEmits<{
  fetchData: [];
}>();

// 生命周期
onMounted(() => {
  initDict();
});

// 监听tab切换
watch(activeName, (newVal) => {
  console.log('Tab切换到:', newVal);
});
</script>

<style lang="scss" scoped>
.code-editor-section {
  min-height: 500px;
}

.code-editor-container {
  border: 1px solid rgba(0, 0, 0, 0.12);
  border-radius: 4px;
  overflow: hidden;
}

.code-textarea {
  :deep(.v-field__input) {
    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
    font-size: 13px;
    line-height: 1.4;
  }

  :deep(textarea) {
    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
    font-size: 13px;
    line-height: 1.4;
  }
}

.file-tabs {
  :deep(.v-slide-group__content) {
    display: flex;
    flex-wrap: nowrap;
  }
}

.file-content {
  min-height: 400px;
}

.file-tab {
  min-width: 120px !important;
  // max-width: 200px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 8px;

  .tab-text {
    flex: 1;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
    margin-right: 4px;
  }

  .close-btn {
    opacity: 0.7;
    transition: opacity 0.2s;
    flex-shrink: 0;

    &:hover {
      opacity: 1;
    }
  }
}

.add-tab {
  min-width: 100px !important;
  flex-shrink: 0;
  color: rgba(0, 0, 0, 0.6);

  &:hover {
    color: rgba(0, 0, 0, 0.8);
  }
}
</style>
